home *** CD-ROM | disk | FTP | other *** search
/ Aminet 41 / Aminet 41 (2001)(Schatztruhe)[!][Feb 2001].iso / Aminet / dev / c / libiconv_src.lha / src / utf8.h < prev    next >
Encoding:
C/C++ Source or Header  |  2000-11-07  |  3.1 KB  |  109 lines

  1. /*
  2.  * UTF-8
  3.  */
  4.  
  5. /* Specification: RFC 2279 */
  6.  
  7. static int
  8. utf8_mbtowc (conv_t conv, wchar_t *pwc, const unsigned char *s, int n)
  9. {
  10.   unsigned char c = s[0];
  11.  
  12.   if (c < 0x80) {
  13.     *pwc = c;
  14.     return 1;
  15.   } else if (c < 0xc2) {
  16.     return RET_ILSEQ;
  17.   } else if (c < 0xe0) {
  18.     if (n < 2)
  19.       return RET_TOOFEW(0);
  20.     if (!((s[1] ^ 0x80) < 0x40))
  21.       return RET_ILSEQ;
  22.     *pwc = ((wchar_t) (c & 0x1f) << 6)
  23.            | (wchar_t) (s[1] ^ 0x80);
  24.     return 2;
  25.   } else if (c < 0xf0) {
  26.     if (n < 3)
  27.       return RET_TOOFEW(0);
  28.     if (!((s[1] ^ 0x80) < 0x40 && (s[2] ^ 0x80) < 0x40
  29.           && (c >= 0xe1 || s[1] >= 0xa0)))
  30.       return RET_ILSEQ;
  31.     *pwc = ((wchar_t) (c & 0x0f) << 12)
  32.            | ((wchar_t) (s[1] ^ 0x80) << 6)
  33.            | (wchar_t) (s[2] ^ 0x80);
  34.     return 3;
  35.   } else if (c < 0xf8 && sizeof(wchar_t)*8 >= 32) {
  36.     if (n < 4)
  37.       return RET_TOOFEW(0);
  38.     if (!((s[1] ^ 0x80) < 0x40 && (s[2] ^ 0x80) < 0x40
  39.           && (s[3] ^ 0x80) < 0x40
  40.           && (c >= 0xf1 || s[1] >= 0x90)))
  41.       return RET_ILSEQ;
  42.     *pwc = ((wchar_t) (c & 0x07) << 18)
  43.            | ((wchar_t) (s[1] ^ 0x80) << 12)
  44.            | ((wchar_t) (s[2] ^ 0x80) << 6)
  45.            | (wchar_t) (s[3] ^ 0x80);
  46.     return 4;
  47.   } else if (c < 0xfc && sizeof(wchar_t)*8 >= 32) {
  48.     if (n < 5)
  49.       return RET_TOOFEW(0);
  50.     if (!((s[1] ^ 0x80) < 0x40 && (s[2] ^ 0x80) < 0x40
  51.           && (s[3] ^ 0x80) < 0x40 && (s[4] ^ 0x80) < 0x40
  52.           && (c >= 0xf9 || s[1] >= 0x88)))
  53.       return RET_ILSEQ;
  54.     *pwc = ((wchar_t) (c & 0x03) << 24)
  55.            | ((wchar_t) (s[1] ^ 0x80) << 18)
  56.            | ((wchar_t) (s[2] ^ 0x80) << 12)
  57.            | ((wchar_t) (s[3] ^ 0x80) << 6)
  58.            | (wchar_t) (s[4] ^ 0x80);
  59.     return 5;
  60.   } else if (c < 0xfe && sizeof(wchar_t)*8 >= 32) {
  61.     if (n < 6)
  62.       return RET_TOOFEW(0);
  63.     if (!((s[1] ^ 0x80) < 0x40 && (s[2] ^ 0x80) < 0x40
  64.           && (s[3] ^ 0x80) < 0x40 && (s[4] ^ 0x80) < 0x40
  65.           && (s[5] ^ 0x80) < 0x40
  66.           && (c >= 0xfd || s[1] >= 0x84)))
  67.       return RET_ILSEQ;
  68.     *pwc = ((wchar_t) (c & 0x01) << 30)
  69.            | ((wchar_t) (s[1] ^ 0x80) << 24)
  70.            | ((wchar_t) (s[2] ^ 0x80) << 18)
  71.            | ((wchar_t) (s[3] ^ 0x80) << 12)
  72.            | ((wchar_t) (s[4] ^ 0x80) << 6)
  73.            | (wchar_t) (s[5] ^ 0x80);
  74.     return 6;
  75.   } else
  76.     return RET_ILSEQ;
  77. }
  78.  
  79. static int
  80. utf8_wctomb (conv_t conv, unsigned char *r, wchar_t wc, int n) /* n == 0 is acceptable */
  81. {
  82.   int count;
  83.   if (wc < 0x80)
  84.     count = 1;
  85.   else if (wc < 0x800)
  86.     count = 2;
  87.   else if (wc < 0x10000)
  88.     count = 3;
  89.   else if (wc < 0x200000)
  90.     count = 4;
  91.   else if (wc < 0x4000000)
  92.     count = 5;
  93.   else if (wc <= 0x7fffffff)
  94.     count = 6;
  95.   else
  96.     return RET_ILSEQ;
  97.   if (n < count)
  98.     return RET_TOOSMALL;
  99.   switch (count) { /* note: code falls through cases! */
  100.     case 6: r[5] = 0x80 | (wc & 0x3f); wc = wc >> 6; wc |= 0x4000000;
  101.     case 5: r[4] = 0x80 | (wc & 0x3f); wc = wc >> 6; wc |= 0x200000;
  102.     case 4: r[3] = 0x80 | (wc & 0x3f); wc = wc >> 6; wc |= 0x10000;
  103.     case 3: r[2] = 0x80 | (wc & 0x3f); wc = wc >> 6; wc |= 0x800;
  104.     case 2: r[1] = 0x80 | (wc & 0x3f); wc = wc >> 6; wc |= 0xc0;
  105.     case 1: r[0] = wc;
  106.   }
  107.   return count;
  108. }
  109.